﻿using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI.HtmlControls;
using System.Collections.Generic;
using TA.JSON;
using System.IO;
using System.Web.UI;
using System.ComponentModel;
using System.Text;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.Xml;
using System.Collections.Specialized;
using System.Reflection;
using System.Threading;
using System.Collections;
using TA.Turbo.Controls;
using TA.DotNetUtils;

namespace TA.Turbo
{
	public partial class TPage
	{
		#region INTERNAL
		#region CONST/STATIC
		//static Delegate SetIntrinsics = typeof(Page).GetMethod(
		//  "SetIntrinsics",
		//  BindingFlags.NonPublic | BindingFlags.Instance,
		//  null,
		//  new Type[] { typeof(HttpContext) },
		//  new System.Reflection.ParameterModifier[0])
		//  .GetMethodBody(
		static MethodInfo mSetIntrinsics = typeof(Page).GetMethod(
			"SetIntrinsics",
			BindingFlags.NonPublic | BindingFlags.Instance,
			null,
			new Type[] { typeof(HttpContext) },
			new System.Reflection.ParameterModifier[0]);

		static MethodInfo mPerformPreInit = typeof(Page).GetMethod(
			"PerformPreInit",
			BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod,
			null,
			new Type[] { },
			null);

		static MethodInfo mInitRecursive = typeof(TControl).GetMethod(
			"InitRecursive",
			BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod,
			null,
			new Type[] { typeof(TControl) },
			null);

		static FieldInfo f_fOnFormRenderCalled = typeof(Page).GetField(
			"_fOnFormRenderCalled",
			 BindingFlags.NonPublic | BindingFlags.Instance);

		static FieldInfo f_requestValueCollection = typeof(Page).GetField(
			"_requestValueCollection",
			 BindingFlags.NonPublic | BindingFlags.Instance);

		static FieldInfo f_items = typeof(Page).GetField(
			"_items",
			 BindingFlags.NonPublic | BindingFlags.Instance);

		static PropertyInfo p_ClientState = typeof(Page).GetProperty(
			"ClientState",
			 BindingFlags.NonPublic | BindingFlags.Instance);

		static Regex rgxGetPath = new Regex("^.*/");

		const string 
			ScriptTagStart = @"<script type=""text/javascript"">",
			ScriptTagEnd = @"</script>",
			JSLinksInit = @"var allAnchors = document.getElementsByTagName(""A"");
for(var i = 0; i < allAnchors.length; ++i)
{
	var a = allAnchors[i];
	if(a.getAttribute(""hrefjs"") != null)
		a.setAttribute(""href"", a.getAttribute(""hrefjs""));
}
";
		internal const string EmptyPostScenarioId = "_psEmpty";
		#endregion
		#region VARS
		#region FOR FACTORY
		/// <summary>
		/// This is for PageHandlerFactory to maintain proper caching.
		/// </summary>
		internal string _url;
		///// <summary>
		///// This is for PageHandlerFactory to maintain proper caching.
		///// </summary>
		//internal bool _recompile;
		#endregion
		#endregion
		#region PROPS
		internal Control SpecialContainer { get { return this._specialContainer; } }
		internal List<Manager> Managers { get { return _managers; } }
		internal List<TurboProgress> ProgressControls { get { return _progressControls; } }
		internal new List<BaseValidator> Validators { get { return _validators; } }
		/// <summary>
		/// Gets true if current request has to be validated, otherwise false.
		/// </summary>
		bool NeedValidation
		{
			get
			{
				return CurrentScenario == null || CurrentScenario.CausesValidation;
			}
		}
		/// <summary>
		/// Gets the hash code of all necessary includes.
		/// </summary>
		int IncludesHashCode
		{
			get
			{
				long hash = 0;
				foreach (string key in this.AllIncludes.Keys)
					hash = (hash + key.GetHashCode()) % int.MaxValue;
				return (int)hash;
			}
		}
		protected internal StateBag ControlState
		{
			get
			{
				return this._controlState;
			}
		}
		#endregion
		#region METHODS
		#region HANDLERS
		//void btnRecompile_Click(object sender, EventArgs e)
		//{
		//  IDictionaryEnumerator en = this.Cache.GetEnumerator();
		//  while (en.MoveNext())
		//    this.Cache.Remove((string)en.Key);

		//  _recompile = true;
		//}
		#endregion
		#region HELPERS
		string ControlStateToBase64()
		{
			//object[] stateArray = new object[this._controlsRequiringControlState.Count];
			//for (int i = 0; i < this._controlsRequiringControlState.Count; ++i)
			//{
			//  IHasControlState c = this._controlsRequiringControlState[i];
			//  StateBag stateBag = c.GetStateBag();

			//  KeyValuePair<string, object>[] cState = new KeyValuePair<string, object>[stateBag.Count];
			//  int iProp = 0;
			//  foreach (string propName in stateBag.Keys)
			//  {
			//    cState[iProp] = new KeyValuePair<string, object>(propName, stateBag[propName]);
			//    ++iProp;
			//  }

			//  stateArray[i] = cState;
			//}

			object[] stateArray = new object[this._controlsRequiringControlState.Count];
			for (int i = 0; i < this._controlsRequiringControlState.Count; ++i)
			{
				IHasControlState c = this._controlsRequiringControlState[i];
				StateBag stateBag = c.GetStateBag();

				object[] cState = new object[stateBag.Count];
				int iProp = 0;
				foreach (string propName in stateBag.Keys)
				{
					cState[iProp] = stateBag[propName];
					++iProp;
				}

				stateArray[i] = cState;
			}

			MemoryStream m = new MemoryStream();
			new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter().Serialize(m, stateArray);
			byte[] data = m.ToArray();

			return new ObjectStateFormatter().Serialize(stateArray);
		}
		void Base64ToControlState(string base64)
		{
			//object[] stateArray = (object[])new ObjectStateFormatter().Deserialize(base64);
			//for (int i = 0; i < this._controlsRequiringControlState.Count; ++i)
			//{
			//  IHasControlState c = this._controlsRequiringControlState[i];
			//  KeyValuePair<string, object>[] cState = (KeyValuePair<string, object>[])stateArray[i];

			//  StateBag stateBag = c.GetStateBag();

			//  stateBag.Clear();
			//  foreach (KeyValuePair<string, object> kvp in cState)
			//  {
			//    stateBag[kvp.Key] = kvp.Value;
			//  }
			//}
			object[] stateArray = (object[])new ObjectStateFormatter().Deserialize(base64);
			for (int i = 0; i < this._controlsRequiringControlState.Count; ++i)
			{
				IHasControlState c = this._controlsRequiringControlState[i];
				object[] cState = (object[])stateArray[i];

				StateBag stateBag = c.GetStateBag();

				int iProp = 0;
				foreach (string propName in stateBag.Keys)
				{
					stateBag[propName] = cState[iProp];
					++iProp;
				}
			}

		}
		#endregion
		#endregion
		#endregion
	}
	static class _StringBuilderExtensions
	{
		internal static void AppendScript(this StringBuilder sb, string url)
		{
			sb.AppendFormat("<script type=\"text/javascript\" src=\"{0}\"></script>\r\n", url);
		}
		internal static void AppendStyle(this StringBuilder sb, string url)
		{
			sb.AppendFormat("<link rel=\"stylesheet\" type=\"text/css\" href=\"{0}\" />\r\n", url);
		}
	}
}